#ifndef _OH_CONTAINER_H
#define	_OH_CONTAINER_H
/*******************************************************************************
 ** Name: container.h                                                         **
 ** Description:                                                              **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved 2-clause BSD License                **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  Redistribution and use in source and binary forms, with or without       **
 **  modification, are permitted provided that the following conditions are   **
 **  met:                                                                     **
 **                                                                           **
 **  * Redistributions of source code must retain the above copyright notice, **
 **    this list of conditions and the following disclaimer.                  **
 **  * Redistributions in binary form must reproduce the above copyright      **
 **    notice, this list of conditions and the following disclaimer in the    **
 **    documentation and/or other materials provided with the distribution.   **
 **                                                                           **
 **  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS      **
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED **
 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           **
 ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT        **
 ** HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    **
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  **
 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR    **
 ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    **
 ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      **
 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        **
 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              **
 **                                                                           **
 ******************************************************************************/
// Modified $Date: 2011-10-22 02:09:07 +0000 (Sat, 22 Oct 2011) $ by $Author: gian.james $
#define _container_h_ID    "$Id: container.hpp 146 2011-10-22 02:09:07Z gian.james $"

#include <iostream>
#include <list>
#include <vector>
#include "object.hpp"
#include "npc.hpp"

#define DEFAULT_DOOR_HP     75
#define DEFAULT_CAPACITY	75

enum class ContainerType {
    Unknown, Area, Vehicle, Object, Room,
    max
};

// Container flags
#define CONTAINER_IS_OPEN	0x01
#define CONTAINER_IS_LOCKED	0x02

class Character;
//! The base container class.
class Container : public WorldObject
{
public:
    Container(std::string n);	// should not be allowed to be called.
    Container(ContainerType t, std::string n);
    Container(const Container& orig);
    virtual ~Container();

    virtual std::string    TypeToStr() { return "Container"; }
    inline ContainerType    CType() const { return ctype; }

    inline void     AddObject(WorldObject * o) { contains.push_back(o); }
    inline void     RemoveObject(WorldObject *o) { contains.remove(o); }

private:
    ContainerType       ctype;
    std::list<WorldObject* > contains;
    flags8				containerFlags;
    int                 dc;
    int					keyID;	// if key, this is the id
    int					capacity;
};

//////////////////////////[ Door
// Door flags
#define DOOR_LOCKED		0x0001
#define DOOR_PICKABLE	0x0002
#define DOOR_TRAPPED	0x0004
#define DOOR_DAMAGABLE	0x0008
#define DOOR_HAS_KEY	0x0010
#define DOOR_HAS_INT	0x0020	// is the door sentient?
#define DOOR_IS_OPEN	0x0040
#define DOOR_IS_HIDDEN	0x0080
#define DOOR_CAN_UNLOCK	0x0100
#define DOOR_CAN_LOCK	0x0200
#define DOOR_IS_SMASHABLE 0x0400

//! Every dog has its day and every area has it's door.
class Door : public WorldObject
{
public:
    Door(std::string n);

    std::string    TypeToStr() { return "Door"; }
    void		DC(int dc) { unlockDC = dc; }
    void		HP(int h) { hp = h; }
    void		DoorFlag(int f) { BMSET(dflags,f); }
    void		Tag(std::string t) { tag = t; }
    void		KeyID(int k) { keyID = k; }

    const int	DC() const { return unlockDC; }
    const int	HP() const { return hp; }
    const flags16 Flags() const { return dflags; }

    
private:
    int     unlockDC;     //!< doors can be picked if locked
    int     hp;     //!< or smashed
    flags16	dflags;
    int		keyID;	// id of any keys to this door
    int		area1, area2;	// ids of connected areas.
};

///////////////////////////////[ Area
// Area flags
#define ROOM_PVP_ENA		0x01
#define ROOM_HAS_CONTENTS	0x02
#define ROOM_IS_OUTDOORS	0x04
#define ROOM_IS_SILENT		0x08

typedef uint8_t areaFlags;

enum class RoomType { Shop, Bank, AuctionHouse, Residence, Business, Government,
	Road, Outside,
	max
};

class Area;
// Not the smallest container, but smaller than an area
class Room : public Container
{
public:
    Room(std::string n);


protected:
    std::string					title;
    std::string					ldesc_light;	// description when there's light (ie daytime)
    std::string					ldesc_dark;	// desc when it's dark (ie night)

    std::map<Door*,Area*>  		doors;
    std::list<Character *>      players;
    std::list<NPC *>			npcs;
    unsigned int                locid;      //!< location ID (from DB)
    uint8_t						flags;
    time_t						lastReset;
    RoomType					roomType;
};

//! An area is a big container...that can contain rooms.
#define AREA_PVP_ENA		0x01

class Area : public Container
{
public:
	Area(std::string n);

private:
	std::string		title;
	std::list<Room *> rooms;
	areaFlags		flags;
};

#define FLAG_TRAIT_VCL_EJS      0x0001    // ejection seats
#define FLAG_TRAIT_VCL_TRA      0x0002   // traction
#define FLAG_TRAIT_VCL_SEA      0x0004   // sealed
#define FLAG_TRAIT_VCL_FLA      0x0008	//<! flammable
#define FLAG_TRAIT_VCL_DEP      0x0010	//<! dependable
#define FLAG_TRAIT_VCL_UDE      0x0020
#define FLAG_TRAIT_VCL_ATV      0x0040    // 4wheeler
#define FLAG_TRAIT_VCL_ECM      0x0080    // electronic countermeasures
#define FLAG_TRAIT_VCL_COM      0x0100    // satellite comm system
#define FLAG_TRAIT_VCL_ARM      0x0200   // armored
#define FLAG_TRAIT_VCL_FLY      0x0400   // flying
#define FLAG_TRAIT_VCL_WPN      0x0800   // mounted weapons
#define FLAG_TRAIT_VCL_UPG		0x1000	 // upgradeable

// Flags
#define FLAG_REQUIRES_TRAINING	0x01

enum class VehicleTypeEnum { Car, Truck, Jeep, Tank, APC, Helicopter, Airplane, Jet, Boat };
enum class VehicleClassEnum { Treaded, Wheeled, Rotor, Jet, Propeller };
class Vehicle : public Container
{
public:
	Vehicle(std::string n);

	VehicleClassEnum	VehicleClass() { return vclass; }
	VehicleTypeEnum		VehicleType() { return vtype; }
	flags16	&			VehicleTraits() { return traits; }

	int					RequiresTraining() { return(vflags & FLAG_REQUIRES_TRAINING); }
	void				RequiresTraining(bool t) { if (t) BMSET(vflags,FLAG_REQUIRES_TRAINING); else BMCLR(vflags,FLAG_REQUIRES_TRAINING); }

protected:
	VehicleClassEnum	vclass;
	VehicleTypeEnum		vtype;
	flags16			traits;
	int				pilotDC;	// difficulty to pilot/drive/steer
	flags8			vflags;
};


#endif	/* _OH_CONTAINER_H */

